package com.utils;


import com.enums.ErrorCodeEnum;

import java.rmi.ServerException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * @description 时间工具类
 * @author firr
 * @date 2023/1/3 9:42
 */
public class DateUtil {
    /**
     * 默认日期格式
     */
    private static final String DATE_DEFAULT = "yyyy-MM-dd";
    /**
     * 完整日期格式
     */
    private static final String DATE_DEFAULT_FULL = "yyyy-MM-dd HH:mm:ss";
    /**
     * 日期格式:年-月
     */
    private static final String MONTH_DATE_DEFAULT = "yyyy-MM";
    /**
     * 日期格式:时间毫秒
     */
    private static final String DATE_TIME_MILLIS = "yyyyMMddhhmmss";

    public static LocalDate dateToLocalDate(Date date) {
        if (EmptyUtil.isEmpty(date)) {
            date = new Date();
        }

        Instant instant = date.toInstant();
        return instant.atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static String dateToDefault(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_DEFAULT);
        return dateFormat.format(date);
    }

    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static String localDateToDefaultStr(LocalDate localDate) {
        if (EmptyUtil.isEmpty(localDate)) {
            return null;
        }

        return localDate.format(DateTimeFormatter.ofPattern(DATE_DEFAULT));
    }

    /**
     * String转LocalDateTime,日期格式目前仅以长度判断,不符合将抛日期不支持异常
     * @author firr
     * @date 2022/7/18 10:55
     * @param str 日期字符串
     * @return java.time.LocalDateTime
     */
    public static Date strToDate(String str) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_DEFAULT);
        try {
            return dateFormat.parse(str);
        } catch (Exception e) {
            throw ServiceException.buildByErrorEnum(ErrorCodeEnum.TIME_FORMAT_NOT_SUPPORT);
        }
    }

    public static String dayStrBetweenLocalDate(LocalDate startDate, LocalDate endDate) {

        if (EmptyUtil.isEmpty(startDate) || EmptyUtil.isEmpty(endDate)) {
            return null;
        }

        return (endDate.toEpochDay() - startDate.toEpochDay()) + "天";
    }

    /**
     * String转LocalDateTime,日期格式目前仅以长度判断,不符合将抛日期不支持异常
     * @author firr
     * @date 2022/7/18 10:55
     * @param str 日期字符串
     * @return java.time.LocalDateTime
     */
    public static LocalDateTime strToLocalDateTime(String str) throws ServerException {
        DateTimeFormatter df;
        if (str.length() == 10) {
            df = DateTimeFormatter.ofPattern(DATE_DEFAULT);
            return LocalDateTime.parse(str, df);
        } else if (str.length() == 19) {
            df = DateTimeFormatter.ofPattern(DATE_DEFAULT_FULL);
            return LocalDateTime.parse(str, df);
        }
        throw ServiceException.buildByErrorEnum(ErrorCodeEnum.TIME_FORMAT_NOT_SUPPORT);
    }

    /**
     * 毫秒字符串转date
     * @author firr
     * @date 2022/12/19 16:08
     * @param timeMillisStr 毫秒字符串
     * @return java.util.Date
     */
    public static Date timeMillisStrToDate(String timeMillisStr) {
        if (EmptyUtil.isEmpty(timeMillisStr) || timeMillisStr.length() != 14) {
            return null;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_MILLIS);
        try {
            return dateFormat.parse(timeMillisStr);
        } catch (Exception e) {
            throw ServiceException.buildByErrorEnum(ErrorCodeEnum.TIME_FORMAT_NOT_SUPPORT);
        }
    }

    public static String localDateTimeToDefaultStr(LocalDateTime localDateTime) {
        if (EmptyUtil.isEmpty(localDateTime)) {
            return null;
        }


        return localDateTime.format(DateTimeFormatter.ofPattern(DATE_DEFAULT));
    }

    public static String localDateTimeToTimeMilliStr(LocalDateTime localDateTime) {
        if (EmptyUtil.isEmpty(localDateTime)) {
            return null;
        }

        return localDateTime.format(DateTimeFormatter.ofPattern(DATE_TIME_MILLIS));
    }

    public static String localDateTimeToMonthStr(LocalDateTime localDateTime) {
        if (EmptyUtil.isEmpty(localDateTime)) {
            return null;
        }

        return localDateTime.format(DateTimeFormatter.ofPattern(MONTH_DATE_DEFAULT));
    }

    public static String localDateTimeToDefaultFullStr(LocalDateTime localDateTime) {
        if (EmptyUtil.isEmpty(localDateTime)) {
            return null;
        }

        return localDateTime.format(DateTimeFormatter.ofPattern(DATE_DEFAULT_FULL));
    }

    public static long getDaysBetweenDate(LocalDate endDate, LocalDate startDate) {
        return endDate.toEpochDay() - startDate.toEpochDay();
    }

    public static boolean timeStrOverlap(String timeStr, String periodStart, String periodEnd) {
        String[] timeHourAndMin = timeStr.split(":");
        String[] periodStartTimeHourAndMin = periodStart.split(":");
        String[] periodEndTimeHourAndMin = periodEnd.split(":");

        LocalTime time = LocalTime.of(Integer.parseInt(timeHourAndMin[0]), Integer.parseInt(timeHourAndMin[1]));
        LocalTime periodStartTime = LocalTime.of(Integer.parseInt(periodStartTimeHourAndMin[0]), Integer.parseInt(periodStartTimeHourAndMin[1]));
        LocalTime periodEndTime = LocalTime.of(Integer.parseInt(periodEndTimeHourAndMin[0]), Integer.parseInt(periodEndTimeHourAndMin[1]));

        return time.isAfter(periodStartTime) && time.isBefore(periodEndTime);
    }

    public static boolean timeStrAfterAnother(String newStartTime, String startTime) {
        String[] timeHourAndMin = newStartTime.split(":");
        String[] newTimeHourAndMin = startTime.split(":");

        LocalTime time = LocalTime.of(Integer.parseInt(timeHourAndMin[0]), Integer.parseInt(timeHourAndMin[1]));
        LocalTime newTime = LocalTime.of(Integer.parseInt(newTimeHourAndMin[0]), Integer.parseInt(newTimeHourAndMin[1]));
        return time.isAfter(newTime);
    }

    // 获得某天最大时间 2020-02-19 23:59:59
    public static Date getEndOfDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());;
        LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
        return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    // 获得某天最小时间 2020-02-17 00:00:00
    public static Date getStartOfDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }
}
